home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / alpha / dipc / dipc-0.000 / dipc-0 / dipc-0.15 / dipcd / support.c < prev    next >
C/C++ Source or Header  |  1996-07-16  |  10KB  |  459 lines

  1.  
  2. /*
  3.  * support.c
  4.  *
  5.  * part of dipcd source code
  6.  *
  7.  * Copyright (C) Kamran Karimi
  8.  */
  9.  
  10. #include "dipcd.h"
  11. #include "funcs.h"
  12.  
  13. extern struct sockaddr_in MY_LBACK, REFEREE_LBACK;
  14. extern struct sockaddr_in MY_ADDRESS, REFEREE_ADDRESS;
  15.  
  16. extern int verbose;
  17.  
  18. char mstr[160];
  19.  
  20. /* prints a message for the user */
  21. void mess(char *str, char *filename, int line)
  22. {
  23.  fprintf(stderr,"[%d@%s:%d]  %s\n",getpid(), filename, line, str);
  24.  
  25.  
  26. /** The following is for the support of heterogeneous systems **/
  27.  
  28. /* converts a 16 bit integer from big/little endian to little/big endian */
  29. /*static*/ short endian16(short to_convert)
  30. {
  31.  char temp;
  32.  union
  33.  {
  34.   short short_form;
  35.   char chr_form[2];
  36.  } conv;
  37.  
  38.  conv.short_form = to_convert;
  39.  temp = conv.chr_form[0];
  40.  conv.chr_form[0] = conv.chr_form[1];
  41.  conv.chr_form[1] = temp;
  42.  
  43.  return conv.short_form;
  44. }
  45.  
  46. /* converts a 32 bit integer from big/little endian to little/big endian */
  47. /*static*/ int endian32(int to_convert)
  48. {
  49.  char temp;
  50.  union
  51.  {
  52.   int int_form;
  53.   char chr_form[4];
  54.  } conv;
  55.  
  56.  conv.int_form = to_convert;
  57.  temp = conv.chr_form[0];
  58.  conv.chr_form[0] = conv.chr_form[3];
  59.  conv.chr_form[3] = temp;
  60.  temp = conv.chr_form[1];
  61.  conv.chr_form[1] = conv.chr_form[2];
  62.  conv.chr_form[2] = temp;
  63.  
  64.  return conv.int_form;
  65. }
  66.  
  67. /* put here the code to convert the fields of a message structure to
  68.    the receiving machine's suitable form. message.arch has the architecture
  69.    of the sender machine. MY_DIPC_ARCH has the architecture of this machine.*/ 
  70. static void convert_message(struct message *message)
  71. {
  72.  
  73.  if(message->arch == MY_DIPC_ARCH)
  74.   return;
  75.  /* else convert (struct message*) message */
  76.  
  77. /* this routine is the place where data conversions for different computer
  78.    architectures are done. This is done after we have converted the message 
  79.    itself. see above. */
  80. static void convert_data(char *data, struct message *message)
  81.  if(message->arch == MY_DIPC_ARCH)
  82.   return;
  83.  switch(message->info.func)
  84.  {
  85.   case SEMCTL:
  86.   /* 'message->info.arg2' has the second (semnum) argument */
  87.    switch(message->info.arg3)
  88.    {
  89.     case SETVAL:
  90.      /* convert (int) message->info.arg4 */
  91.      break;
  92.    
  93.     case IPC_SET:
  94.     case IPC_STAT:      
  95.      /* convert (struct semid_ds *) data */
  96.      break;
  97.    
  98.     case SETALL:
  99.     case GETALL:
  100.      /* convert (ushort *)data */
  101.      break;
  102.    }
  103.    break;
  104.      
  105.   case SEMOP:
  106.    /* 'message->info.arg2' has the third (nops) argument */
  107.    /* convert (struct sembuf *) data */
  108.    break;
  109.  
  110.   case MSGCTL:
  111.    /* convert (struct msqid_ds *) data */
  112.    break;
  113.    
  114.   case SHMCTL:
  115.    /* (struct shmid_ds *) data */
  116.    break;
  117.   
  118.   default:
  119.    sprintf(mstr,"ERROR: Unknown Function");
  120.    mess(mstr, INFO);
  121.    break;
  122.  }  
  123. }   
  124. /** End of heterogeneous support routines **/
  125.  
  126.  
  127. char *work_string(int func)
  128. {
  129.  static char strings[23][11] = 
  130.  {
  131.   "SEMOP     ",
  132.   "SEMCTL    ",
  133.  
  134.   "MSGSND    ",
  135.   "MSGRCV    ",
  136.   "MSGCTL    ",
  137.  
  138.   "SHMCTL    ",
  139.  
  140.   "DISABLE_RD",
  141.   "DISABLE_WR",
  142.  
  143.   "WANTRD    ",
  144.   "WANTWR    ",
  145.   "DETACH    ",
  146.   "AK        ",
  147.   
  148.   "WRPROT_SND",
  149.   "RDPROT    ",
  150.   "RDPROT_SND",
  151.   "NOP_SND   ",
  152.   "RCV       ",
  153.   "TSTGET    ",
  154.   
  155.   "RMID      ",
  156.   "DELKEY    ",
  157.   "SEARCH    ",
  158.   "COMMIT    ",
  159.   "Bad Work  "
  160.  };
  161.  
  162.  switch(func)
  163.  {
  164.   case SEMOP: return strings[0];
  165.   case SEMCTL: return strings[1];
  166.  
  167.   case MSGSND: return strings[2];
  168.   case MSGRCV: return strings[3];
  169.   case MSGCTL: return strings[4];
  170.  
  171.   case SHMCTL: return strings[5];
  172.  
  173.   case DISABLE_RD: return strings[6];
  174.   case DISABLE_WR: return strings[7];
  175.   case WANTRD: return strings[8];
  176.   case WANTWR: return strings[9];
  177.   case DETACH: return strings[10];
  178.   case AK: return strings[11];
  179.   
  180.   case WRPROT_SND: return strings[12];
  181.   case RDPROT: return strings[13];
  182.   case RDPROT_SND: return strings[14];
  183.   case NOP_SND: return strings[15];
  184.   case RCV: return strings[16];
  185.   case TSTGET: return strings[17];
  186.   
  187.   case RMID: return strings[18];
  188.   case DELKEY: return strings[19];
  189.   case SEARCH: return strings[20];
  190.   case COMMIT: return strings[21];
  191.  
  192.   default:
  193.    break;
  194.  }
  195.  sprintf(mstr,"ERROR: Bad Work function: %d", func);
  196.  mess(mstr, INFO);
  197.  return strings[22];
  198. }
  199.  
  200.  
  201. char *request_string(int req)
  202. {
  203.  static char strings[7][12] = 
  204.  {
  205.   "REQ_SHMMAN ",
  206.   "RES_SHMMAN ",
  207.  
  208.   "REQ_REFEREE",
  209.   "RES_REFEREE",
  210.   
  211.   "REQ_DOWORK ",
  212.   "RES_DOWORK ",
  213.   
  214.   "Bad Request"
  215.  };
  216.  
  217.  switch(req)
  218.  {
  219.   case REQ_SHMMAN: return strings[0];
  220.   case RES_SHMMAN: return strings[1];
  221.  
  222.   case REQ_REFEREE: return strings[2];
  223.   case RES_REFEREE: return strings[3];
  224.   
  225.   case REQ_DOWORK: return strings[4];
  226.   case RES_DOWORK: return strings[5];
  227.  
  228.   default:
  229.    break;
  230.  }
  231.  sprintf(mstr,"ERROR: Bad Request: %d", req);
  232.  mess(mstr, INFO);
  233.  return strings[6];
  234. }
  235.  
  236. /* read nbytes from the network and put them in *ptr */
  237. int readn(int fd, char *ptr, int nbytes)
  238. {
  239.  int nleft, nread;
  240.  
  241.  nleft = nbytes;
  242.  while(nleft > 0)
  243.  {
  244.   nread = read(fd,ptr,nleft);
  245.   if(nread < 0)
  246.   {
  247.    if(errno != EINTR)
  248.     break;
  249.   }    
  250.   if(nread == 0) break;
  251.   if(nread > 0)
  252.   {
  253.    nleft -= nread;
  254.    ptr += nread;
  255.   } 
  256.  } 
  257.  return (nbytes - nleft);
  258. }  
  259.  
  260. /* send nbytes from *ptr to the network */
  261. int writen(int fd, char *ptr, int nbytes)
  262. {
  263.  int nleft,nwritten;
  264.  
  265.  nleft = nbytes;
  266.  while(nleft > 0)
  267.  {
  268.   nwritten = write(fd,ptr,nleft);
  269.   if(nwritten < 0)
  270.   {
  271.    if(errno != EINTR)
  272.     break;
  273.   }
  274.   if(nwritten == 0) break;
  275.   if(nwritten > 0)
  276.   {
  277.    nleft -= nwritten;
  278.    ptr += nwritten;
  279.   } 
  280.  } 
  281.  return (nbytes - nleft);
  282. }
  283.  
  284. /* prepare a socket to receive incoming conections */
  285. FD plug(int family, struct sockaddr *my_addr, int addr_len)
  286. {
  287.  FD sockfd;
  288.  
  289.  if((sockfd = socket(family,SOCK_STREAM,0)) < 0)
  290.  {
  291.   sprintf(mstr,"ERROR: socket() Failed  BECAUSE %s",strerror(errno));
  292.   mess(mstr, INFO); 
  293.   return BAD_FD;
  294.  }
  295.  if(bind(sockfd,my_addr,addr_len) < 0)
  296.  {
  297.   sprintf(mstr,"ERROR: bind() Failed  BECAUSE %s",strerror(errno));
  298.   mess(mstr, INFO);
  299.   close(sockfd);
  300.   return BAD_FD;
  301.  }
  302.  if(listen(sockfd,5) < -1)
  303.  {
  304.   sprintf(mstr,"ERROR: listen() Failed BECAUSE %s",strerror(errno));
  305.   mess(mstr, INFO);
  306.   close(sockfd);
  307.   return BAD_FD;
  308.  }
  309.  return sockfd;
  310. }
  311.  
  312. /* get a socket connection to another waiting one */ 
  313. FD ring(int family, struct sockaddr *addr, int addr_len)
  314. {
  315.  int sockfd;
  316.  sigset_t newmask, oldmask;
  317.  
  318.  sigemptyset(&newmask);
  319.  sigaddset(&newmask, SIGCHLD);
  320.  sigprocmask(SIG_BLOCK, &newmask, &oldmask);
  321.  while(1)
  322.  {
  323.   if((sockfd = socket(family,SOCK_STREAM,0)) < 0) 
  324.   {
  325.    if(errno != EINTR)
  326.    {
  327.     sprintf(mstr,"ERROR: socket() Failed  BECAUSE %s",strerror(errno));
  328.     mess(mstr, INFO);
  329.     sigprocmask(SIG_SETMASK, &oldmask, NULL);
  330.     return BAD_FD;
  331.    }
  332.   }
  333.   else break;
  334.  }
  335.  if(family == AF_INET)
  336.  {
  337.   if(SAME_ADDRESS((struct sockaddr_in *)addr, MY_ADDRESS))
  338.    (struct sockaddr_in *)addr = &MY_LBACK;
  339.   else if(SAME_ADDRESS((struct sockaddr_in *)addr, REFEREE_ADDRESS) && 
  340.           SAME_MACHINE((struct sockaddr_in *)addr,MY_ADDRESS))
  341.    (struct sockaddr_in *)addr = &REFEREE_LBACK;  
  342.  }   
  343.  /* connect() may not be able to restart in case of an intr */
  344.  while(1)
  345.  {
  346.   if(connect(sockfd, addr, addr_len) < 0)
  347.   {
  348.    if(errno != EINTR)
  349.    {
  350.     sprintf(mstr,"ERROR: connect() Failed  BECAUSE %s",strerror(errno));
  351.     mess(mstr, INFO);
  352.     close(sockfd);
  353.     sigprocmask(SIG_SETMASK, &oldmask, NULL);
  354.     return BAD_FD;
  355.    }
  356.   }
  357.   else break;
  358.  }
  359.  sigprocmask(SIG_SETMASK, &oldmask, NULL); 
  360.  return sockfd;
  361. }
  362.  
  363.  
  364. /* send the contents of a struct message over an internet connection */ 
  365. BOOLEAN send_in_message(struct message *message, struct sockaddr_in addr)
  366.  int in_sock;
  367.  int want_trans, act_trans;
  368.  
  369.  message->arch = MY_DIPC_ARCH;
  370.  message->reserved = -1;
  371.  in_sock = ring(AF_INET, (struct sockaddr *) &addr, sizeof(addr));
  372.  if(in_sock < 0)
  373.  {
  374.   sprintf(mstr,"ERROR: Can't Connect To Internet address BECAUSE %s",
  375.           strerror(errno));
  376.   mess(mstr, INFO);
  377.   return FAIL;
  378.  } 
  379.  want_trans = sizeof(*message);
  380.  act_trans = writen(in_sock, (char *)message, want_trans);
  381.  if(act_trans < want_trans)
  382.  {
  383.   sprintf(mstr,"ERROR: Sent %d From %d Bytes BECAUSE %s",
  384.           act_trans, want_trans,strerror(errno));
  385.   mess(mstr, INFO); 
  386.   close(in_sock);
  387.   return FAIL;
  388.  }
  389.  close(in_sock);
  390.  return SUCCESS;
  391. }
  392.   
  393. /* receive some data (for example message contents) over an internet 
  394.    connection */  
  395. int get_in_data(int in_sock, char *data, struct message *message)
  396. {
  397.  int act_trans;
  398.  
  399.  act_trans = readn(in_sock, data, message->info.dsize);
  400.  if(act_trans == message->info.dsize)
  401.   convert_data(data, message);
  402.  return act_trans;
  403.  
  404. /* receive an struct message from an internet connection */
  405. int get_in_message(int in_sock, struct message *message)
  406. {
  407.  int act_trans;
  408.  
  409.  act_trans = readn(in_sock, (char *)message, sizeof(struct message));
  410.  if(act_trans == sizeof(struct message))
  411.   convert_message(message);
  412.  return act_trans;
  413.  
  414. /* called from front_end.c and back_end.c, when a child exits */
  415. void child_handler(int signo)
  416. {
  417.  pid_t cpid;
  418.  
  419.  /* consider the possibility of multiple exits */
  420.  while((cpid = waitpid(-1, NULL, WNOHANG)) > 0)
  421.  {
  422.   if(verbose)
  423.   {
  424.    sprintf(mstr,"Child %d Exited",cpid);
  425.    mess(mstr, INFO);
  426.   } 
  427.  }
  428. }
  429.  
  430.  
  431. BOOLEAN become(char *user)
  432. {
  433.  struct passwd *pw;
  434.  
  435.  pw = getpwnam(user);
  436.  if(pw)
  437.  {
  438.   if((setegid(pw->pw_gid) < 0) || (seteuid(pw->pw_uid) < 0))
  439.   {
  440.    sprintf(mstr,"ERROR: Can't Become: %s, uid: %d, gid: %d. Because: %s",
  441.                    user, pw->pw_uid, pw->pw_gid, strerror(errno));
  442.    mess(mstr, INFO);
  443.    printf("euid %d  egid %d  uid %d  gid %d\n",geteuid(), getegid(),
  444.     getuid(), getgid());
  445.    return FAIL;
  446.   }
  447.   return SUCCESS;
  448.  }
  449.  sprintf(mstr,"ERROR: User '%s' Not Found", user);
  450.  mess(mstr, INFO);
  451.  return FAIL;
  452. }
  453.